﻿/**
* ...
* @author Fabien ANTOINE
*/

package xul;

#if neko

import neko.io.Path;
import neko.io.File;
import neko.io.FileOutput;
import haxe.io.Bytes;

#end

import Xml;

import xul.elem.Window;
import xul.elem.XulElement;

class XulBuilder
{
	private var __xul:XulElement;
	
	public var Container( getContainer, null ):XulElement;
	public var StyleSheets:Array<String>;
	
	public function new( ?main:XulElement ) 
	{
		__xul = ( main == null ? new Window() : main );
		
		StyleSheets = new Array<String>();
	}
	
	private function getContainer():XulElement { return __xul; }
	
	public function addElement( e:XulElement ):Void
	{
		__xul.addChild( e );
	}
	
	public function build():String
	{
		var x:Xml = Xml.createDocument();
		
		#if ( flash9 || js || neko || php )
		x.addChild( Xml.createProlog( "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" ) );
		
		for( i in StyleSheets ) x.addChild( Xml.createProlog( "<?xml-stylesheet href=\"" + i + "\" type=\"text/css\"?>" ) );
		#end
		
		var xml = _buildXml( __xul );
		
		xml.set( "xmlns", "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" );
		xml.set( "xmlns:html", "http://www.w3.org/1999/xhtml" );
		
		x.addChild( xml );
		
		return x.toString();
	}
	
	#if neko
	public function buildXul( path:String, ?addExt:Bool )
	{
		var p = new Path( if( addExt != null && addExt == true ) path + ".xul" else path );
		var c = build();
		var out:FileOutput = File.write( p.toString(), false );
		out.write( Bytes.ofString( c ) );
		
		out.close();
	}
	#end
	
	
	private function _buildXml( xl:XulElement ):Xml
	{
		var name = Type.getClassName( Type.getClass( xl ) ).split( "." );
		var x:Xml = Xml.createElement( name[ name.length - 1 ].toLowerCase() );

		for( s in Type.getInstanceFields( Type.getClass( xl ) ) )
		{
			// Avoid intern variables
			if( StringTools.startsWith( s, "__" ) ) continue;
			
			var value = Reflect.field( xl, s );
			
			if( value != null && !Reflect.isFunction( value ) )
			{
				x.set( _correctAttributeName( s ), _correctAttributeValue( value ) );
			}
		}
		
		// Add childs
		if( xl.hasChildNodes() )
			for( e in xl.getChilds() )
				x.addChild( _buildXml( e ) );
		
		return x;
	}
	
	private function _correctAttributeName( name:String ):String
	{
		return if( name == "className" ) "class";
			   else if( name == "varName" ) "var";
			   else StringTools.replace( name, "_", "-" );
	}
	
	private function _correctAttributeValue( value:Dynamic ):String
	{
		var s = Std.string( value );
		return if( Type.getEnum( value ) != null ) StringTools.replace( s, "_", "-" ); else s;
	}
}